import moment = require("moment");
import KeyValuePairsDb, { KVPair, OperableStoreShow, ResultType } from "logic/database/KeyValuePairsDb";

import { v4 as uuidv4 } from "uuid";
import { moment_format } from "logic/tools/common";
function to_new_id(set_count: number) {
    return `${set_count+1}0${uuidv4().replace(/[^\w]/g, '')}`;
}

/**
 * 读取参数: 学习内容
 */
interface MReadParam_StudyItem {
    /** 标识ID */
    id?: string;
    /** 类型 */
    type?: string;
    /** 学习内容 */
    conent?: string;
}
/** 模型: 学习项 */
interface MStudyItem {
    /** 标识ID */
    id: string;
    /** 类型 */
    type: string;
    /** 学习内容 */
    conent: string;
    /** 开始学习时间 */
    start_time: string;
    /** 备注 */
    remark?: string;
}

/**
 * 接口: 学习内容
 */
interface IStudyController extends ICRUDAsyncController<MStudyItem, MReadParam_StudyItem, string> {
    GetTypeList(): string[];
}

/**
 * 获取实例接口: 学习内容
 * @param store
 * @returns 实现实例
 */
function GetCase_IStudyController(store: OperableStoreShow): IStudyController {
    return new StudyController(store);
}

export {
    MReadParam_StudyItem,
    MStudyItem,
    IStudyController,
    GetCase_IStudyController,
}

class StudyController implements IStudyController {
    private cache_list: MStudyItem[];
    private readonly db: KeyValuePairsDb;
    private readonly store: OperableStoreShow;

    constructor(store: OperableStoreShow) {
        this.cache_list = [];
        this.db = new KeyValuePairsDb();
        this.store = store;
    }
    GetTypeList(): string[] {
        let self = this;
        if (!self.cache_list || self.cache_list.length <= 0) {
            return [];
        }
        let s = new Set<string>();
        for (let i = 0; i < self.cache_list.length; i++) {
            const m = self.cache_list[i];
            if (m.type) {
                s.add(m.type)
            }
        }
        return Array.from<string>(s);
    }

    async CreateOrUpdateAsync(m: MStudyItem): Promise<ExecuteResult> {
        let self = this;
        console.log('EditStudy(CreateOrUpdate).m:', m);
        if (!m.start_time) {
            m.start_time = moment().format(moment_format.normal);
        }

        if (!m.id) {
            m.id = to_new_id(self.cache_list.length);

            self.cache_list.push(m);
            self.UpdateStudyList();
            return { IsSuccess: true };
        }
        for (let index = 0; index < self.cache_list.length; index++) {
            const element = self.cache_list[index];
            if (element.id === m.id) {
                self.cache_list[index] = m;
                break;
            }
        }
        self.UpdateStudyList();
        return { IsSuccess: true };
    }
    async ReadListAsync(param: MReadParam_StudyItem): Promise<ExecuteResultData<MStudyItem[]>> {
        let self = this;
        let r: ExecuteResultData<MStudyItem[]> = {
            IsSuccess: false,
            Data: [],
        };
        if (self.cache_list.length <= 0) {
            let key: string = self.GKey_StudyList();
            let result:ResultType<KVPair> = await self.db.Read(self.store.Name, key);
            if (result.Code != 0) {
                r.Message = "查询结果为空";
                console.log(r, key, self.store);
                return r;
            }
            let dict = result.Data;
            self.cache_list = dict[key];
        }
        r.Data = self.cache_list;
        r.Data = self.filterResultList(r.Data, param);
        r.IsSuccess = true;
        return r;
    }
    private filterResultList(source: MStudyItem[], param: MReadParam_StudyItem) {
        let rlist: MStudyItem[] = [];
        for (let i = 0; i < source.length; i++) {
            const m = source[i];

            let wheres:boolean[] = [];
            if (param.id) {
                wheres.push(param.id === m.id);
            }
            if (param.type) {
                wheres.push(m.type == param.type);
            }
            if (param.conent) {
                wheres.push((m.conent || "").indexOf(param.conent) > -1);
            }

            let is_show: boolean = true;
            for (let i_where = 0; i_where < wheres.length; i_where++) {
                const w = wheres[i_where];
                if (w == null) {
                    continue;
                }
                is_show = is_show && w;
            }
            if (is_show) {
                rlist.push(m);
            }
        }
        return rlist;
    }

    async DeletesAsync(ids: string[]): Promise<ExecuteResultData<number>> {
        let self = this;
        let oper_count = 0;
        for (let index_m = self.cache_list.length -1; index_m >= 0; index_m--) {
            const m = self.cache_list[index_m];
            let is_have: boolean = false;
            for (let index_id = 0; index_id < ids.length; index_id++) {
                const del_id = ids[index_id];
                if (m.id === del_id) {
                    is_have = true;
                    break;
                }
            }
            if (is_have) {
                self.cache_list.splice(index_m, 1);
                oper_count++;
            }
        }
        self.UpdateStudyList();
        return { IsSuccess: true, Data: oper_count };
    }
    private GKey_StudyList() {
        return "EspinhoMemoryTable:StudyList";
    };
    private async UpdateStudyList() {
        let self = this;
        let key = self.GKey_StudyList();
        let dict: KVPair = {};
        dict[key] = self.cache_list;
        let result:ResultType<number> = await self.db.Write(self.store.Name, dict);
        if (result.Code != 0) {
            console.log("写入数据失败", key, self.store);
        }
    }
}
